package com.drinks.yiniang.io.http;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.drinks.yiniang.common.help.UserTokenSingleton;
import com.drinks.yiniang.utils.SharedPreUtils;
import com.hansen.library.Constants;
import com.hansen.library.io.kit.ThreadPoolKit;
import com.hansen.library.io.tuple.Tuple2;
import com.hansen.library.listener.BitmapCallback;
import com.hansen.library.listener.Callback;
import com.hansen.library.listener.OnDownloadListener;
import com.hansen.library.utils.LogUtils;
import com.hansen.library.utils.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Dispatcher;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by han on 2017/5/19 0019.
 */
public class OkHttpIO {
    private static volatile OkHttpIO instance;
    private Handler mHandler;
    public OkHttpClient okHttpClient;

    static public OkHttpIO getInstance() {
        if (instance == null) {
            synchronized (OkHttpIO.class) {
                if (instance == null) {
                    instance = new OkHttpIO();
                }
            }
        }
        return instance;
    }

    public OkHttpIO() {
        this.mHandler = new Handler(Looper.getMainLooper());
        //配置 client
        Dispatcher dispatcher = new Dispatcher(ThreadPoolKit.createThreadPoolExecutor(1, 12, 60l, TimeUnit.SECONDS, "app-http"));
        //最大并发访问
        dispatcher.setMaxRequests(10);
        this.okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(appendHeaderParamInterceptor)
                .dispatcher(dispatcher)
                .build();
    }

    private Interceptor appendHeaderParamInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            //通过newBuilder 拿到Builder
            Headers.Builder builder = request.
                    headers().
                    newBuilder();

            // add common header
            String userToken = UserTokenSingleton.getInstance().getGlobalUserToken();

            if(!StringUtils.isEmpty(userToken)) {
                builder.add("Authorization", "Bearer " + userToken);
            }

            Request newRequest = request.newBuilder()
                    .headers(builder.build())
                    .build();

            return chain.proceed(newRequest);
        }
    };

    /**
     * 发起 GET 请求
     *
     * @param url
     * @return
     */
    public Call get(@NonNull String url, @Nullable RequestBody requestBody) {
        LogUtils.d("--->url: " + url);

        Request.Builder mBuilder = new Request.Builder()
                .url(url)
                .get();



        Request request = mBuilder.build();

        return okHttpClient.newCall(request);
    }

    /**
     * 发起 GET 请求
     *
     * @param url
     * @param callback
     */
    public void get(@NonNull String url, @Nullable RequestBody requestBody, @Nullable final Callback<Tuple2<Integer, String>, Exception> callback) {
        get(url, requestBody).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final int responseCode = response.code();
                final String responseStr = response.body().string();

                LogUtils.d("---请求返回码：" + responseCode);
                LogUtils.d("---请求返回信息：" + responseStr);

                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(new Tuple2(responseCode, responseStr));
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call call, final IOException e) {
                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onError(e);
                        }
                    });
                }
            }
        });
    }

    /**
     * 发起 GET 请求
     *
     * @param url
     * @param callback
     */
    public void getBitmap(@NonNull String url, @Nullable final BitmapCallback<Bitmap, String> callback) {
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //获取流
                InputStream in = response.body().byteStream();
                //转化为bitmap
                final Bitmap bitmap = BitmapFactory.decodeStream(in);

                in.close();

                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(bitmap);
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call call, final IOException e) {
                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onError(e.getMessage());
                        }
                    });
                }
            }
        });
    }

    /**
     * 发起 POST
     *
     * @param url
     * @param requestBody
     * @return
     */
    public Call post(@NonNull String url, @Nullable RequestBody requestBody) {
        //如果请求的数据为空，则给定一个空的表单，进行提交
        if (requestBody == null) {
            requestBody = new FormBody.Builder().build();
        }

        LogUtils.d("--->url: " + url);

        //构造请求, Builder().tag(url)
        Request.Builder mBuilder = new Request.Builder().url(url)
                .post(requestBody);

        Request request = mBuilder.build();

        return okHttpClient.newCall(request);
    }

    /**
     * 发起 POST
     *
     * @param url
     * @param requestBody
     * @param callback
     */
    public void post(@NonNull String url, @Nullable RequestBody requestBody, @Nullable final Callback<Tuple2<Integer, String>, Exception> callback) {
        //如果请求的数据为空，则给定一个空的表单，进行提交
        if (requestBody == null) {
            requestBody = new FormBody.Builder().build();
        }

        //构造请求
        post(url, requestBody).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final int responseCode = response.code();
                final String responseStr = response.body().string();

                if(!StringUtils.isEmpty(response.header("access-token"))) {//刷新token
                    SharedPreUtils.getInstance().saveUserToken(response.header("access-token"));
                }

                LogUtils.d("---请求返回码：" + responseCode);
                LogUtils.d("---请求返回信息：" + responseStr);

                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(new Tuple2(responseCode, responseStr));
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call call, final IOException error) {
                LogUtils.e("--->error: " + error.getMessage() + "  " + error);

                if (callback != null) {
                    mHandler.post(new Runnable() {
                        @Override
                            public void run() {
                            callback.onError(error);
                        }
                    });
                }
            }
        });
    }

    /**
     * 文件下载
     *
     * @param url              下载连接
     * @param savePath         储存下载文件的SDCard目录
     * @param downloadListener 下载监听
     */
    public void postDownload(@NonNull String url, @NonNull final String savePath, @NonNull final String saveName, @Nullable final OnDownloadListener downloadListener) {
        //构造请求
        Request request = new Request.Builder()
                .url(url)
                .build();
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final int code = response.code();

                LogUtils.d("---请求返回码：" + code);

                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;

                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    File file = new File(savePath, saveName);
                    fos = new FileOutputStream(file);
                    long sum = 0;

                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;

                        // 下载中
                        downloadListener.onDownloading(total, sum);
                    }

                    fos.flush();

                    // 下载完成
                    downloadListener.onDownloadSuccess();
                } catch (Exception e) {
                    downloadListener.onDownloadFailed(e);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }

            @Override
            public void onFailure(Call call, IOException e) {
                if (downloadListener != null) {
                    downloadListener.onDownloadFailed(e);
                }
            }
        });
    }

    /**
     * 文件下载
     *
     * @param url              下载连接
     * @param saveFile         储存下载文件File
     * @param downloadListener 下载监听
     */
    public void postDownload(@NonNull String url, @NonNull final File saveFile, @Nullable final OnDownloadListener downloadListener) {
        //构造请求
        Request request = new Request.Builder()
                .url(url)
                .build();
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final int code = response.code();

                LogUtils.d("---请求返回码：" + code);

                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;

                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();

                    fos = new FileOutputStream(saveFile);
                    long sum = 0;

                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;

                        // 下载中
                        downloadListener.onDownloading(total, sum);
                    }

                    fos.flush();

                    // 下载完成
                    downloadListener.onDownloadSuccess();
                } catch (Exception e) {
                    downloadListener.onDownloadFailed(e);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }

            @Override
            public void onFailure(Call call, IOException e) {
                if (downloadListener != null) {
                    downloadListener.onDownloadFailed(e);
                }
            }
        });
    }

    /**
     * 根据Tag取消请求
     */
    public void cancelTag(Object tag) {
        if (okHttpClient == null || tag == null) return;

        for (Call call : okHttpClient.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
        for (Call call : okHttpClient.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }

    /**
     * 取消所有请求请求
     */
    public void cancelAll() {
        if (okHttpClient == null) {
            return;
        }

        for (Call call : okHttpClient.dispatcher().queuedCalls()) {
            call.cancel();
        }
        for (Call call : okHttpClient.dispatcher().runningCalls()) {
            call.cancel();
        }
    }

    public void cancelAllRunning() {
        if (okHttpClient == null) {
            return;
        }

        for (Call call : okHttpClient.dispatcher().runningCalls()) {
            call.cancel();
        }
    }
}
